package sdk.webview.fmc.com.fmcsdk.util;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;
import okio.Buffer;

/**
 * 提供了多种初始化方法看自己情况
 * 双向验证initSslSocketFactory
 * 单向验证bks证书initSslSocketFactorySingle 至于bks证书的生成方式自行百度很多
 * 单向验证crt证书initSslSocketFactorySingleBuyCrt
 */
public class HttpsUtils {
    private static final String KEY_STORE_TYPE_BKS = "bks";
    private static final String KEY_STORE_TYPE_P12 = "PKCS12";
    public static final String KEY_STORE_PASSWORD = "123456";//P12文件密码
    public static final String BKS_STORE_PASSWORD = "123456";//BKS文件密码
    public static SSLSocketFactory sSLSocketFactory;
    public static X509TrustManager trustManager;

    /**
     * 双向校验中SSLSocketFactory X509TrustManager 参数的生成
     *
     * @param application
     */
    public static void initSslSocketFactory(Application application) {
        try {
            InputStream bksStream = application.getAssets().open("xxxx.bks");//客户端信任的服务器端证书流
            InputStream p12Stream = application.getAssets().open("xxxx.p12");//服务器需要验证的客户端证书流

            // 客户端信任的服务器端证书
            KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);
            // 服务器端需要验证的客户端证书
            KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);

            try {
                trustStore.load(bksStream, BKS_STORE_PASSWORD.toCharArray());//加载客户端信任的服务器证书
                keyStore.load(p12Stream, KEY_STORE_PASSWORD.toCharArray());//加载服务器信任的客户端证书
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } finally {
                try {
                    bksStream.close();
                    p12Stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);
            trustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());//生成用来校验服务器真实性的trustManager


            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
            keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());//生成服务器用来校验客户端真实性的KeyManager
            //初始化SSLContext
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
            sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 单向校验中SSLSocketFactory X509TrustManager 参数的生成
     * 通常单向校验一般都是服务器不校验客户端的真实性，客户端去校验服务器的真实性
     *
     * @param application
     */
    public static void initSslSocketFactorySingle(Application application) {
        try {
            InputStream bksStream = application.getAssets().open("xxxx.bks");//客户端信任的服务器端证书流

            // 客户端信任的服务器端证书
            KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);

            try {
                trustStore.load(bksStream, BKS_STORE_PASSWORD.toCharArray());//加载客户端信任的服务器证书
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } finally {
                try {
                    bksStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);
            trustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());//生成用来校验服务器真实性的trustManager

            SSLContext sslContext = SSLContext.getInstance("TLSv1", "AndroidOpenSSL");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            //初始化SSLContext
            sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 单向校验中,通过crt格式的证书生成SSLSocketFactory X509TrustManager 参数的生成
     * 通常在Android中，客户端用于校验服务器真实性的证书是支持BKS格式的，但是往往后台给的证书都是crt格式的
     * 当然我们可以自己生成BKS，但是想更方便一些我们也是可以直接使用crt格式的证书的
     *
     * @param application
     */
    public static SSLSocketFactory initSslSocketFactorySingleBuyCrt(Context application) {
        try {
            InputStream crtStream = application.getAssets().open("eam.crt");//客户端信任的服务器端证书流

            CertificateFactory cf = CertificateFactory.getInstance("X.509", "AndroidOpenSSL");//
            Certificate ca = cf.generateCertificate(crtStream);
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore trustStore = KeyStore.getInstance(keyStoreType);

            try {
                trustStore.load(null, null);
                trustStore.setCertificateEntry("ca", ca);
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } finally {
                try {
                    crtStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);
            trustManager = chooseTrustManager(trustManagerFactory.getTrustManagers());//生成用来校验服务器真实性的trustManager

            SSLContext sslContext = SSLContext.getInstance("TLSv1", "AndroidOpenSSL");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            //初始化SSLContext
            sSLSocketFactory = sslContext.getSocketFactory();//通过sslContext获取到SocketFactory

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sSLSocketFactory;
    }

    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
        for (TrustManager trustManager : trustManagers) {
            if (trustManager instanceof X509TrustManager) {
                return (X509TrustManager) trustManager;
            }
        }
        return null;
    }

    public static SSLSocketFactory test(Context context) {
        String password = "password";
        InputStream inputStream = null;
        try {
            inputStream = context.getAssets().open("haeco-eamuat.fm-community.com.pem");

            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate clientCert = (X509Certificate) certificateFactory.generateCertificate(inputStream);
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            keyStore.setCertificateEntry("client", clientCert);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
            kmf.init(keyStore, password.toCharArray());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
            return sslContext.getSocketFactory();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //	证书信息进行缩减
    private static String CER_BAIDU = "-----BEGIN CERTIFICATE-----\n" +
            "MIIG0jCCBbqgAwIBAgIQASP53519pWCLdzj4xmZCITANBgkqhkiG9w0BAQsFADBP\n" +
            "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSkwJwYDVQQDEyBE\n" +
            "aWdpQ2VydCBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTAeFw0yMzAyMjgwMDAwMDBa\n" +
            "Fw0yNDAzMzAyMzU5NTlaMHgxCzAJBgNVBAYTAkhLMRgwFgYDVQQHEw9OZXcgVGVy\n" +
            "cml0b3JpZXMxNzA1BgNVBAoTLkhvbmcgS29uZyBBaXJjcmFmdCBFbmdpbmVlcmlu\n" +
            "ZyBDb21wYW55IExpbWl0ZWQxFjAUBgNVBAMTDWVhbS5oYWVjby5jb20wggEiMA0G\n" +
            "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqkqw8BRByFJY8aBd0JmUtsR7LzH4V\n" +
            "pbEK/xqtDpLzWsjcG1uD0X/+A4AMhv91tsTqrw/vz03soCnHVcx9qeGRkbO1+knV\n" +
            "SNAKz2f3FKjsH2rpoJ0WZbl2ROylxqSUsMyT3LpzMRwpoUcdfy0Q8D+F0qHyekWs\n" +
            "etduBjjmHPH7AjKNiBLb4E08RitIRY9gj8avj/3i1fm6ala+YulDieLVNwD5lqjz\n" +
            "rCdVPcxzqJZSRwSCtOR/nEdP5cC12YXfs9Rcdjavj6jg+3QjMnoPWtxwo2WUmkq9\n" +
            "zlo9S+QWlwjBv+Q1FnRr3C3yhdxzeYNgh8Eq6RXHpeHuJo78I3wDovmDAgMBAAGj\n" +
            "ggN/MIIDezAfBgNVHSMEGDAWgBS3a6LqqKqEjHnqtNoPmLLFlXa59DAdBgNVHQ4E\n" +
            "FgQUrS50N32omI9uVRFbfXJgTlUXsnEwKwYDVR0RBCQwIoINZWFtLmhhZWNvLmNv\n" +
            "bYIRd3d3LmVhbS5oYWVjby5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG\n" +
            "CCsGAQUFBwMBBggrBgEFBQcDAjCBjwYDVR0fBIGHMIGEMECgPqA8hjpodHRwOi8v\n" +
            "Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUTFNSU0FTSEEyNTYyMDIwQ0ExLTQu\n" +
            "Y3JsMECgPqA8hjpodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRUTFNS\n" +
            "U0FTSEEyNTYyMDIwQ0ExLTQuY3JsMD4GA1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYI\n" +
            "KwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzB/BggrBgEFBQcB\n" +
            "AQRzMHEwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBJBggr\n" +
            "BgEFBQcwAoY9aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExT\n" +
            "UlNBU0hBMjU2MjAyMENBMS0xLmNydDAJBgNVHRMEAjAAMIIBfQYKKwYBBAHWeQIE\n" +
            "AgSCAW0EggFpAWcAdQDuzdBk1dsazsVct520zROiModGfLzs3sNRSFlGcR+1mwAA\n" +
            "AYaWH0dTAAAEAwBGMEQCIFhL1uzyhiFTqag32kP3tPjlRlXEGoIlDhokmQwC4gGk\n" +
            "AiA2F9T1+tQbYCZ/x4EV8JN9AXAYfLCkgZD6dSPfMlxmbQB2AHPZnokbTJZ4oCB9\n" +
            "R53mssYc0FFecRkqjGuAEHrBd3K1AAABhpYfR8YAAAQDAEcwRQIhAJSIFlBKJA16\n" +
            "FOxSoqEiDplpDENqx93eK0wYX2ALy5/nAiBtyP8bgpNSKCsQJxkdYXJRzOwKUxe2\n" +
            "1kgkatN5IJxl5QB2AEiw42vapkc0D+VqAvqdMOscUgHLVt0sgdm7v6s52IRzAAAB\n" +
            "hpYfR48AAAQDAEcwRQIhAPsu2CvdTPyEco9YeVcLMaQP+VVMcdU5Q19zH0NXOUd2\n" +
            "AiBxRd1nslUqBfukrnHsx8wvA21BX4NF+1R0YmkEnjNGgzANBgkqhkiG9w0BAQsF\n" +
            "AAOCAQEAQ2dK/qXovUJutlapalFuQEvU9WeFEu3wCdLl666okUC7Tl5goiDm80zG\n" +
            "CLJEh6cPaqBIFAU/wLbQy2C3p/mymh96wv/PDB3qWs9ngKp0WSfrOiRhbonvHvSi\n" +
            "ugtNyuX8HaptFfEBsknbLZluS40ioAQXaSp7WrpUjEh1FuPHgZ4BXj5FMTjmF6tp\n" +
            "Hn75cyt0YsZuAWALD7PDZ5MQMEwpG05F7MLiouwugk6EajAFoaKTniYg66wDqiS0\n" +
            "3JQqmLXOXHcHrhpXtW90cwHXkK/VfhVzxvlDktCo91kSiRzFcrXUU3uEkLGm1UqS\n" +
            "J7H/i6HDBpdOxqPV9jdnICe2Kvt82A==\n" +
            "-----END CERTIFICATE-----\n";

    //设置安全证书
    public static SSLSocketFactory setSafeOkHttpClient() {
        try {
            InputStream certificate = new Buffer().writeUtf8(CER_BAIDU).inputStream();
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            keyStore.setCertificateEntry("ca", certificateFactory.generateCertificate(certificate));
            certificate.close();

            SSLContext sslContext = SSLContext.getInstance("SSL");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
            return sslContext.getSocketFactory();

        } catch (Exception e) {
        }
        return null;
    }

    private static boolean isHave = true;




    /**
     * 功能：检测当前URL是否可连接或是否有效,
     * 描述：最多连接网络 x次, 如果 x 次都不成功，视为该地址不可用
     * @return true是可以上网，false是不能上网
     */
    private static URL url;
    private static HttpURLConnection con;
    private static int state = -1;
    public static boolean isNetOnline(Context context) {
        // Android 4.0 之后不能在主线程中请求HTTP请求
        int counts = 0;
        boolean isNetsOnline = true;
        while (counts < 2) {
            try {
                SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
                final String address = sharedPrefs.getString(Constant.BASE_ADDRESS_URL, "");
                url = new URL(address);
                con = (HttpURLConnection) url.openConnection();
                state = con.getResponseCode();
                Log.e("FragmentNet", "isNetOnline counts: " + counts + "=state: " + state);
                if (state == 200) {
                    isNetsOnline = true;
                }
                break;
            } catch (Exception ex) {
                isNetsOnline = false;
                counts++;
                Log.e("FragmentNet", "isNetOnline URL不可用，连接第 " + counts + " 次");
                continue;
            }
        }
        return isNetsOnline;

    }


    public static List<String> getIps(String ipString) {
        String regEx = "((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
        List<String> ips = new ArrayList<String>();
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(ipString);
        while (m.find()) {
            String result = m.group();
            ips.add(result);
        }
        return ips;
    }

    public static boolean isEmpty(final Collection<?> coll) {
        return coll == null || coll.isEmpty();
    }
}